home *** CD-ROM | disk | FTP | other *** search
/ PC World Interactive 7 / PC World Interactive 7.iso / program / ctutor.exe / TEXT / CHAP10.TXT < prev    next >
Text File  |  1994-05-15  |  19KB  |  406 lines

  1.  
  2.  
  3.  
  4.                                                        Chapter 10
  5.                                                 FILE INPUT/OUTPUT
  6.  
  7. OUTPUT TO A FILE
  8. -----------------------------------------------------------------
  9. Load and display the file named FORMOUT.C for   =================
  10. your first example of writing data to a file.       FORMOUT.C
  11. We begin as before with the include statement   =================
  12. for STDIO.H, and include the header for the 
  13. string functions.  Then we define some variables for use in the 
  14. example including a rather strange looking new type.
  15.  
  16. The type FILE is used for a file variable and is defined in the 
  17. STDIO.H file.  It is used to define a file pointer for use in 
  18. file operations.  The definition of C requires a pointer to a 
  19. FILE type to access a file, and as usual, the name can be any 
  20. valid variable name.  Many writers use fp for the name of this 
  21. first example file pointer so I suppose we should start with 
  22. it too.
  23.  
  24.  
  25. OPENING A FILE
  26. -----------------------------------------------------------------
  27. Before we can write to a file, we must open it.  What this really 
  28. means is that we must tell the system that we want to write to a 
  29. file and what the filename is.  We do this with the fopen() 
  30. function illustrated in line 11 of the program.  The file 
  31. pointer, fp in our case, points to the file and two arguments 
  32. are required in the parentheses, the filename first, followed by 
  33. the file attribute.  The filename is any valid DOS filename, and 
  34. can be expressed in upper or lower case letters, or even mixed if 
  35. you so desire.  It is enclosed in double quotes.  For this 
  36. example we have chosen the name TENLINES.TXT.  This file should 
  37. not exist on your disk at this time.  If you have a file with 
  38. this name, you should change its name or move it because when we 
  39. execute this program, its contents will be erased.  If you don't 
  40. have a file by this name, this program will create one and put 
  41. some data into it.
  42.  
  43.  
  44. Note that we are not forced to use a string constant for the file 
  45. name as we have done here.  This is only done here for 
  46. convenience.  We can use a string variable which contains the 
  47. filename then use any method we wish to fill in the name of the 
  48. file to open.  This will be illustrated later in this chapter.
  49.  
  50.  
  51. READING ("r")
  52. -----------------------------------------------------------------
  53. The second parameter is the file attribute and can be any of 
  54. three letters, "r", "w", or "a", and must be lower case.  There 
  55. are actually additional attributes available in C to allow more 
  56.  
  57.                                                         Page 10-1
  58.  
  59.                                    Chapter 10 - File Input/Output
  60.  
  61. flexible I/O, and after you complete your study of this chapter, 
  62. you should check the documentation for your compiler to study the 
  63. additional file opening attributes.  When an "r" is used, the 
  64. file is opened for reading, a "w" is used to indicate a file to 
  65. be used for writing, and an "a" indicates that you desire to 
  66. append additional data to the data already in an existing file.  
  67. Opening a file for reading requires that the file already exist.  
  68. If it does not exist, the file pointer will be set to NULL and 
  69. can be checked by the program.  It is not checked in this 
  70. program, but could be easily checked as follows.
  71.  
  72.    if (fp == NULL) {
  73.       printf("File failed to open\n");
  74.       exit;
  75.    }
  76.  
  77. Good programming practice would dictate that all file pointers be 
  78. checked to assure proper file opening in a manner similar to the 
  79. above code.
  80.  
  81.  
  82. WRITING ("w")
  83. -----------------------------------------------------------------
  84. When a file is opened for writing, it will be created if it does 
  85. not already exist and it will be reset if it does resulting in 
  86. deletion of any data already there.  If the file fails to open 
  87. for any reason, a NULL will be returned so the pointer should be 
  88. tested as above.
  89.  
  90.  
  91. APPENDING ("a")
  92. -----------------------------------------------------------------
  93. When a file is opened for appending, it will be created if it 
  94. does not already exist and it will be initially empty.  If it 
  95. does exist, the data input point will be the end of the present 
  96. data so that any new data will be added to any data that already 
  97. exists in the file.  Once again, the return value can and should 
  98. be checked for proper opening.
  99.  
  100.  
  101. OUTPUTTING TO THE FILE
  102. -----------------------------------------------------------------
  103. The job of actually outputting to the file is nearly identical to 
  104. the outputting we have already done to the standard output 
  105. device.  The only real differences are the new function names and 
  106. the addition of the file pointer as one of the function 
  107. arguments.  In the example program, fprintf() replaces our 
  108. familiar printf() function name, and the file pointer defined 
  109. earlier is the first argument within the parentheses.  The 
  110. remainder of the statement looks like, and in fact is identical 
  111. to, the printf() statement.
  112.  
  113.  
  114.  
  115.                                                         Page 10-2
  116.  
  117.                                    Chapter 10 - File Input/Output
  118.  
  119. CLOSING A FILE
  120. -----------------------------------------------------------------
  121. To close a file, use the function fclose() with the file pointer 
  122. in the parentheses.  Actually, in this simple program, it is not 
  123. necessary to close the file because the system will close all 
  124. open files before returning to DOS.  It would be good 
  125. programming practice for you to get in the habit of closing all 
  126. files in spite of the fact that they will be closed 
  127. automatically, because that would act as a reminder to you of 
  128. what files are open at the end of each program.
  129.  
  130. You can open a file for writing, close it, and reopen it for 
  131. reading, then close it, and open it again for appending, etc.  
  132. Each time you open it, you could use the same file pointer, or 
  133. you could use a different one.  The file pointer is simply a tool 
  134. that you use to point to a file and you decide what file it will 
  135. point to.
  136.  
  137. Compile and run this program.  When you run it, you will not get 
  138. any output to the monitor because it doesn't generate any.  After 
  139. running it, look at your directory for a file named TENLINES.TXT 
  140. and examine it's contents.  That is where your output will be.  
  141. Compare the output with that specified in the program.  It should 
  142. agree.  If you add the pointer test code described above, and if 
  143. the file couldn't be opened for any reason, there will be one 
  144. line of text on the monitor instead of the file listing.
  145.  
  146. Do not erase the file named TENLINES.TXT yet.  We will use it in 
  147. some of the other examples in this chapter.
  148.  
  149.  
  150. OUTPUTTING A SINGLE CHARACTER AT A TIME
  151. -----------------------------------------------------------------
  152. Load the next example file, CHAROUT.C, and        ===============
  153. display it on your monitor.  This program will       CHAROUT.C
  154. illustrate how to output a single character at    ===============
  155. a time.
  156.  
  157. The program begins with the include statement, then defines some 
  158. variables including a file pointer.  The file pointer is named 
  159. point this time, but we could have used any other valid variable 
  160. name.  We then define a string of characters to use in the output 
  161. function using a strcpy() function.  We are ready to open the 
  162. file for appending and we do so with the fopen() function, except 
  163. this time we use the lower cases for the filename.  This is done 
  164. simply to illustrate that DOS doesn't care about the case of the 
  165. filename.  Notice that the file will be opened for appending so 
  166. we will add to the lines inserted during the last program.
  167.  
  168. The program is actually two nested for loops.  The outer loop is 
  169. simply a count to ten so that we will go through the inner loop 
  170. ten times.  The inner loop calls the function putc() repeatedly 
  171.  
  172.  
  173.                                                         Page 10-3
  174.  
  175.                                    Chapter 10 - File Input/Output
  176.  
  177. until a character in the string named others is detected to be a 
  178. zero.  This is the terminating NULL for the string.
  179.  
  180.  
  181. THE putc() FUNCTION
  182. -----------------------------------------------------------------
  183. The part of the program we are interested in is the putc() 
  184. function in line 16.  It outputs one character at a time, the 
  185. character being the first argument in the parentheses and the 
  186. file pointer being the second and last argument.  Why the 
  187. designer of C made the pointer first in the fprintf() function, 
  188. and last in the putc() function is a good question for which 
  189. there may be no answer.  It seems like this would have been a 
  190. good place to have used some consistency.
  191.  
  192. When the textline others is exhausted, a newline is needed 
  193. because a newline was not included in the definition above.  A 
  194. single putc() is then executed which outputs the \n character to 
  195. return the carriage and do a linefeed.
  196.  
  197. When the outer loop has been executed ten times, the program 
  198. closes the file and terminates.  Compile and run this program but 
  199. once again there will be no output to the monitor. 
  200.  
  201. Following execution of the program, examine the contents of the 
  202. file named TENLINES.TXT and you will see that the 10 new lines 
  203. were added to the end of the 10 that already existed.  If you run 
  204. it again, yet another 10 lines will be added.  Once again, do not 
  205. erase this file because we are still not finished with it. 
  206.  
  207.  
  208. READING A FILE
  209. -----------------------------------------------------------------
  210. Load the file named READCHAR.C and display it    ================
  211. on your monitor.  This is our first program         READCHAR.C
  212. which can read from a file.  This program        ================
  213. begins with the familiar include, some data 
  214. definitions, and the file opening statement which should require 
  215. no explanation except for the fact that an "r" is used here 
  216. because we want to read from this file.  In this program, we 
  217. check to see that the file exists, and if it does, we execute the 
  218. main body of the program.  If it doesn't exist, we print a 
  219. message and quit.  If the file does not exist, the system will 
  220. set the pointer equal to NULL which we test in line 11.  If the 
  221. pointer is NULL we display a message and terminate the program.
  222.  
  223. The main body of the program is one do while loop in which a 
  224. single character is read from the file and output to the monitor 
  225. until an EOF (end of file) is detected from the input file.  The 
  226. file is then closed and the program is terminated.
  227.  
  228.  
  229.  
  230.  
  231.                                                         Page 10-4
  232.  
  233.                                    Chapter 10 - File Input/Output
  234.  
  235. CAUTION  CAUTION  CAUTION
  236. -----------------------------------------------------------------
  237. At this point, we have the potential for one of the most common 
  238. and most perplexing problems of programming in C.  The variable 
  239. returned from the getc() function is a character, so we can use a 
  240. char variable for this purpose.  There is a problem that could 
  241. develop here if we happened to use an unsigned char however, 
  242. because C returns a minus one for an EOF.  An unsigned char type 
  243. variable is not capable of containing a negative value.  An 
  244. unsigned char type variable can only have the values of zero to 
  245. 255, so it will return a 255 for a minus one.  This is a very 
  246. frustrating problem to try to find.  The program can never find 
  247. the EOF and will therefore never terminate the loop.  This is 
  248. easy to prevent, always use a char type variable for use in 
  249. returning an EOF.
  250.  
  251. There is another problem with this program but we will worry 
  252. about it when we get to the next program and solve it with the 
  253. one following that.
  254.  
  255. After you compile and run this program and are satisfied with the 
  256. results, it would be a good exercise to change the name of 
  257. TENLINES.TXT and run the program again to see that the NULL test 
  258. actually works as stated.  Be sure to change the name back 
  259. because we are still not finished with TENLINES.TXT.  In a real 
  260. production program, you would not actually terminate the program.  
  261. You would give the user the opportunity to enter another filename 
  262. for input.  We are interested in illustrating the basic file 
  263. handling techniques here, so we are using a very simple error 
  264. handling method.
  265.  
  266.  
  267. READING A WORD AT A TIME
  268. -----------------------------------------------------------------
  269. Load and display the file named READTEXT.C for   ================
  270. an example of how to read a word at a time.         READTEXT.C
  271. This program is nearly identical to the last     ================
  272. except that this program uses the fscanf() 
  273. function to read in a string at a time.  Because the fscanf() 
  274. function stops reading when it finds a space or a newline 
  275. character, it will read a word at a time, and display the results 
  276. one word to a line.  You will see this when you compile and run 
  277. it, but first we must examine a programming problem.
  278.  
  279.  
  280. THIS IS A PROBLEM
  281. -----------------------------------------------------------------
  282. Inspection of the program will reveal that when we read data in 
  283. and detect the EOF, we print out something before we check for 
  284. the EOF resulting in an extra line of printout.  What we usually 
  285. print out is the same thing printed on the prior pass through the 
  286. loop because it is still in the buffer named oneword.  We 
  287. therefore must check for EOF before we execute the printf() 
  288.  
  289.                                                         Page 10-5
  290.  
  291.                                    Chapter 10 - File Input/Output
  292.  
  293. function.  This has been done in READGOOD.C, which you will 
  294. shortly examine, compile, and execute.
  295.  
  296. Compile and execute the original program we have been studying, 
  297. READTEXT.C and observe the output.  If you haven't changed 
  298. TENLINES.TXT you will end up with "Additional" and "lines." on 
  299. two separate lines with an extra "lines." displayed at the end of 
  300. the output because of the printf() before checking for EOF.  Note 
  301. that some compilers apparently clear the buffer after printing so 
  302. you may get an extra blank line instead of two lines with 
  303. "lines." on them.
  304.  
  305.  
  306. NOW LET'S FIX THE PROBLEM
  307. -----------------------------------------------------------------
  308. Compile and execute READGOOD.C and observe that  ================
  309. the extra "lines." does not get displayed           READGOOD.C
  310. because of the extra check for the EOF in the    ================
  311. middle of the loop.  This was also the problem 
  312. referred to when we looked at READCHAR.C, but I chose not to 
  313. expound on it there because the error in the output was not so 
  314. obvious.
  315.  
  316.  
  317. FINALLY, WE READ A FULL LINE
  318. -----------------------------------------------------------------
  319. Load and display the file READLINE.C for an      ================
  320. example of reading a complete line.  This           READLINE.C
  321. program is very similar to those we have been    ================
  322. studying except that we read a complete line 
  323. in this example program.
  324.  
  325. We are using fgets() which reads an entire line, including the 
  326. newline character, into a buffer.  The buffer to be read into is 
  327. the first argument in the function call, and the maximum number 
  328. of characters to read is the second argument, followed by the 
  329. file pointer.  This function will read characters into the input 
  330. buffer until it either finds a newline character, or it reads the 
  331. maximum number of characters allowed minus one.  It leaves one 
  332. character for the end of string NULL character.  In addition, if 
  333. it finds an EOF, it will return a value of NULL.  In our example, 
  334. when the EOF is found, the pointer named c will be assigned the 
  335. value of NULL.  NULL is defined as zero in your STDIO.H file. 
  336.  
  337. When we find that the pointer named c has been assigned the value 
  338. of NULL, we can stop processing data, but we must check before we 
  339. print just like in the last program.  Last of course, we close 
  340. the file.
  341.  
  342. You can add a check for the file pointer being NULL for each of 
  343. these programs if you desire.  In a production program, all 
  344. returned file pointers should be checked.
  345.  
  346.  
  347.                                                         Page 10-6
  348.  
  349.                                    Chapter 10 - File Input/Output
  350.  
  351. HOW TO USE A VARIABLE FILENAME
  352. -----------------------------------------------------------------
  353. Load and display the program ANYFILE.C for an   =================
  354. example of reading from any file.  This             ANYFILE.C
  355. program asks the user for the filename          =================
  356. desired, and reads in the filename, storing 
  357. it in a string.  Then it opens that file for reading.  The entire 
  358. file is then read and displayed on the monitor.  It should pose 
  359. no problems to your understanding so no additional comments will 
  360. be made.
  361.  
  362. Compile and run this program.  When it requests a filename, enter 
  363. the name and extension of any text file available, even one of 
  364. the example C programs.
  365.  
  366. HOW DO WE PRINT?
  367. -----------------------------------------------------------------
  368. Load the last example program in this chapter,   ================
  369. the one named PRINTDAT.C for an example of how      PRINTDAT.C
  370. to print.  This program should not present any   ================
  371. surprises to you so we will move very quickly 
  372. through it.  Once again, we open TENLINES.TXT for reading and we 
  373. open PRN for writing.  Printing is identical to writing data to a 
  374. disk file except that we use a standard name for the filename.  
  375. Most C compilers use the reserved filename of PRN that instructs 
  376. the compiler to send the output to the printer.  There are other 
  377. names that are used occasionally such as LPT, LPT1, or LPT2.  
  378. Check the documentation for your particular compiler.  Some of 
  379. the newest compilers use a predefined file pointer such as stdprn 
  380. for the print file.  Once again, check your documentation.
  381.  
  382. The program is simply a loop in which a character is read, and if 
  383. it is not the EOF, it is displayed and printed.  When the EOF is 
  384. found, the input file and the printer output files are both 
  385. closed.  Note that good programming practice would include 
  386. checking both file pointers to assure that the files were opened 
  387. properly.  You can now erase TENLINES.TXT from your disk.  We 
  388. will not be using it in any of the later chapters.
  389.  
  390. PROGRAMMING EXERCISES
  391. -----------------------------------------------------------------
  392. 1.  Write a program that will prompt for a filename for an input 
  393.     file, prompt for a filename for a write file, and open both 
  394.     plus a file to the printer.  Enter a loop that will read a 
  395.     character, and output it to the file, the printer, and the 
  396.     monitor.  Stop at EOF.
  397.  
  398. 2.  Prompt for a filename to read.  Read the file a line at a 
  399.     time and display it on the monitor with line numbers.
  400.  
  401. 3.  Modify ANYFILE.C to test if the file exists and print a 
  402.     message if it doesn't.  Use a method similar to that used in 
  403.     READCHAR.C.
  404.  
  405.                                                         Page 10-7
  406.